package com.qixiaobao.system.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.qixiaobao.common.annotation.datasource.Third;
import com.qixiaobao.common.constant.CacheConstants;
import com.qixiaobao.common.core.domain.model.LoginUser;
import com.qixiaobao.common.core.redis.RedisCache;
import com.qixiaobao.common.exception.UtilException;
import com.qixiaobao.common.utils.DateUtils;
import com.qixiaobao.common.utils.SecurityUtils;
import com.qixiaobao.common.utils.StringUtils;
import com.qixiaobao.system.domain.Message;
import com.qixiaobao.system.domain.MessageUser;
import com.qixiaobao.system.domain.dto.MessageDTO;
import com.qixiaobao.system.domain.vo.MessageVO;
import com.qixiaobao.system.mapper.MessageMapper;
import com.qixiaobao.system.mapper.MessageUserMapper;
import com.qixiaobao.system.service.IMessageService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * @Description 站内信  业务层处理
 * @Author yangxm
 * @Date 2025/7/1 14:28
 */
@Slf4j
@Service
public class MessageServiceImpl implements IMessageService {

    @Autowired
    private RedisCache redisCache;
    @Autowired
    private MessageMapper messageMapper;
    @Autowired
    private MessageUserMapper messageUserMapper;

    /**
     * @Description 发送BI系统站内信
     * @Author yangxm
     * @Date 2025/7/1 16:55
     * @param message
     * @param receiverIds
     * @return int
     */
    @Third
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int insertBiMessage(Message message, List<Long> receiverIds) {
        checkMessage(message, receiverIds);
        int row = messageMapper.insertMessage(message);
        Long messageId = message.getId();
        for (Long receiverId: receiverIds) {
            if (receiverId == null) {
                continue;
            }
            MessageUser messageUser = new MessageUser();
            messageUser.setMessageId(messageId);
            messageUser.setReceiverId(receiverId);
            messageUserMapper.insertMessageUser(messageUser);
            //存储到redis
            long unReadCount = 0;
            String key = String.format("%s%s:%d", CacheConstants.UN_READ_COUNT_KEY, message.getClient(), receiverId);
            if (redisCache.hasKey(key)){
                unReadCount = redisCache.increment(String.format("%s%s:%d", CacheConstants.UN_READ_COUNT_KEY, message.getClient(), receiverId), 1);
            }else {
                //根据client 和 用户id查询未读消息数量
                unReadCount = messageUserMapper.selectCountByClientAndUserId(message.getClient(), receiverId);
                redisCache.setCacheObject(String.format("%s%s:%d", CacheConstants.UN_READ_COUNT_KEY, message.getClient(), receiverId), unReadCount);
            }
            log.info("{}, 站内信数量：, unReadCount: {}", receiverId, unReadCount);

        }
        return row;
    }

    /**
     * @Description 查询站内信列表
     * @Author yangxm
     * @Date 2025/7/10 16:11
     * @param messageDTO
     * @return java.util.List<com.qixiaobao.system.domain.vo.MessageVO>
     */
    @Override
    public List<MessageVO> selectMessageList(MessageDTO messageDTO) {
        return messageMapper.selectMessageList(messageDTO);
    }

    /**
     * @Description 标记为已读
     * @Author yangxm
     * @Date 2025/7/10 16:11
     * @param messageUserId
     * @return int
     */
    @Override
    public int markAsRead(Long messageUserId) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if (loginUser == null){
            throw new UtilException("登录超时，请重新登陆！");
        }
        //根据消息id和用户id查询消息
        MessageUser messageUser = messageUserMapper.selectMessageUserByIdAndUserId(messageUserId, loginUser.getId());
        if (messageUser == null){
            log.error("站内信, 消息不存在, messageUserId: {}", messageUserId);
            throw new UtilException("站内信, 消息不存在！");
        }
        if (messageUser.getReadFlag() == 0){
            messageUser.setReadFlag(1);
            messageUser.setReadTime(DateUtils.getNowDate());
            int row= messageUserMapper.updateMessageUser(messageUser);

            //存储到redis
            long unReadCount = 0;
            String key = String.format("%s%s:%d", CacheConstants.UN_READ_COUNT_KEY, messageUser.getClient(), loginUser.getId());
            if (redisCache.hasKey(key)){
                unReadCount = redisCache.increment(String.format("%s%s:%d", CacheConstants.UN_READ_COUNT_KEY, messageUser.getClient(), loginUser.getId()), 1);
            }else {
                //根据client 和 用户id查询未读消息数量
                unReadCount = messageUserMapper.selectCountByClientAndUserId(messageUser.getClient(), loginUser.getId());
                redisCache.setCacheObject(String.format("%s%s:%d", CacheConstants.UN_READ_COUNT_KEY, messageUser.getClient(), loginUser.getId()), unReadCount);
            }
            log.info("{}, 站内信数量：, unReadCount: {}", loginUser.getUsername(), unReadCount);
            return row;
        }else {
            log.error("站内信, 已读, messageUserId: {}", messageUserId);
            throw new UtilException("站内信, 已读！");
        }
    }

    /**
     * @Description 删除站内信
     * @Author yangxm
     * @Date 2025/7/10 16:11
     * @param messageUserId
     * @return int
     */
    @Override
    public int deleteMessageUser(Long messageUserId) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if (loginUser == null){
            throw new UtilException("登录超时，请重新登陆！");
        }
        //根据消息id和用户id查询消息
        MessageUser messageUser = messageUserMapper.selectMessageUserByIdAndUserId(messageUserId, loginUser.getId());
        if (messageUser == null){
            log.error("站内信, 消息不存在, messageUserId: {}", messageUserId);
            throw new UtilException("站内信, 消息不存在！");
        }
        messageUser.setFlag("0");
        int row = messageUserMapper.updateMessageUser(messageUser);
        if (messageUser.getReadFlag() == 0){
            //存储到redis
            long unReadCount = 0;
            String key = String.format("%s%s:%d", CacheConstants.UN_READ_COUNT_KEY, messageUser.getClient(), loginUser.getId());
            if (redisCache.hasKey(key)){
                unReadCount = redisCache.increment(String.format("%s%s:%d", CacheConstants.UN_READ_COUNT_KEY, messageUser.getClient(), loginUser.getId()), 1);
            }else {
                //根据client 和 用户id查询未读消息数量
                unReadCount = messageUserMapper.selectCountByClientAndUserId(messageUser.getClient(), loginUser.getId());
                redisCache.setCacheObject(String.format("%s%s:%d", CacheConstants.UN_READ_COUNT_KEY, messageUser.getClient(), loginUser.getId()), unReadCount);
            }
            log.info("{}, 站内信数量：, unReadCount: {}", loginUser.getId(), unReadCount);
        }
        return row;
    }

    /**
     * @Description 批量标记为已读
     * @Author yangxm
     * @Date 2025/7/10 16:11
     * @param messageDTO
     * @return int
     */
    @Override
    public int markAsReadAll(MessageDTO messageDTO) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if (loginUser == null){
            throw new UtilException("登录超时，请重新登陆！");
        }
        if (StringUtils.isEmpty(messageDTO.getMessageUserIdList())){
            throw new UtilException("缺少参数：messageUserIdList");
        }
        List<MessageUser> messageUserList = messageUserMapper.selectMessageUserListByIdListAndUserId(messageDTO.getMessageUserIdList(), loginUser.getId());
        if (StringUtils.isEmpty(messageUserList)){
            throw new UtilException("站内信, 消息不存在！");
        }
        int row = 0;
        for (MessageUser messageUser: messageUserList) {
            if (messageUser.getReadFlag() == 0){
                messageUser.setReadFlag(1);
                messageUser.setReadTime(DateUtils.getNowDate());
                messageUserMapper.updateMessageUser(messageUser);

                //存储到redis
                long unReadCount = 0;
                String key = String.format("%s%s:%d", CacheConstants.UN_READ_COUNT_KEY, messageUser.getClient(), loginUser.getId());
                if (redisCache.hasKey(key)){
                    unReadCount = redisCache.increment(String.format("%s%s:%d", CacheConstants.UN_READ_COUNT_KEY, messageUser.getClient(), loginUser.getId()), 1);
                }else {
                    //根据client 和 用户id查询未读消息数量
                    unReadCount = messageUserMapper.selectCountByClientAndUserId(messageUser.getClient(), loginUser.getId());
                    redisCache.setCacheObject(String.format("%s%s:%d", CacheConstants.UN_READ_COUNT_KEY, messageUser.getClient(), loginUser.getId()), unReadCount);
                }
                log.info("{}, 站内信数量：, unReadCount: {}", loginUser.getId(), unReadCount);
                row++;
            }
        }
        return row;
    }

    /**
     * @Description 批量删除
     * @Author yangxm
     * @Date 2025/7/10 16:11
     * @param messageDTO
     * @return int
     */
    @Override
    public int deleteAll(MessageDTO messageDTO) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if (loginUser == null){
            throw new UtilException("登录超时，请重新登陆！");
        }
        if (StringUtils.isEmpty(messageDTO.getMessageUserIdList())){
            throw new UtilException("缺少参数：messageUserIdList");
        }
        List<MessageUser> messageUserList = messageUserMapper.selectMessageUserListByIdListAndUserId(messageDTO.getMessageUserIdList(), loginUser.getId());
        if (StringUtils.isEmpty(messageUserList)){
            throw new UtilException("站内信, 消息不存在！");
        }
        int row = 0;
        for (MessageUser messageUser: messageUserList) {
            messageUser.setFlag("0");
            messageUserMapper.updateMessageUser(messageUser);
            if (messageUser.getReadFlag() == 0){

                //存储到redis
                long unReadCount = 0;
                String key = String.format("%s%s:%d", CacheConstants.UN_READ_COUNT_KEY, messageUser.getClient(), loginUser.getId());
                if (redisCache.hasKey(key)){
                    unReadCount = redisCache.increment(String.format("%s%s:%d", CacheConstants.UN_READ_COUNT_KEY, messageUser.getClient(), loginUser.getId()), 1);
                }else {
                    //根据client 和 用户id查询未读消息数量
                    unReadCount = messageUserMapper.selectCountByClientAndUserId(messageUser.getClient(), loginUser.getId());
                    redisCache.setCacheObject(String.format("%s%s:%d", CacheConstants.UN_READ_COUNT_KEY, messageUser.getClient(), loginUser.getId()), unReadCount);
                }
                log.info("{}, 站内信数量：, unReadCount: {}", loginUser.getId(), unReadCount);
            }
            row++;
        }
        return row;
    }

    /**
     * @Description 前置校验
     * @Author yangxm
     * @Date 2025/7/2 10:54
     * @param message
     * @param receiverIds
     */
    private void checkMessage(Message message, List<Long> receiverIds) {
        String client = message.getClient();
        if (client == null || StringUtils.isBlank(client = client.trim())) {
            log.error("站内信, 客户端不能为空, message: {}, receiverIds: {}", JSONObject.toJSONString(message), JSONObject.toJSONString(receiverIds));
            throw new UtilException("站内信, 客户端不能为空！");
        }
        message.setClient(client);
        String subject = message.getSubject();
        if (subject == null || StringUtils.isBlank(subject = subject.trim())) {
            log.error("站内信, 主题不能为空, message: {}, receiverIds: {}", JSONObject.toJSONString(message), JSONObject.toJSONString(receiverIds));
            throw new UtilException("站内信, 主题不能为空！");
        }
        message.setSubject(subject);
        String content = message.getContent();
        if (content == null || StringUtils.isBlank(content = content.trim())) {
            log.error("站内信, 内容不能为空, message: {}, receiverIds: {}", JSONObject.toJSONString(message), JSONObject.toJSONString(receiverIds));
            throw new UtilException("站内信, 内容不能为空！");
        }
        message.setContent(content);
        if (receiverIds == null || receiverIds.size() < 1) {
            log.error("站内信, 收信人不能为空, message: {}, receiverIds: {}", JSONObject.toJSONString(message), JSONObject.toJSONString(receiverIds));
            throw new UtilException("站内信, 收信人不能为空！");
        }
    }
}
